home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / dev / devSCSI.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  10KB  |  365 lines

  1. /* 
  2.  * devSCSI.c --
  3.  *
  4.  *    SCSI = Small Computer System Interface. The routines in this file
  5.  *    are indented to aid in formatting SCSI command blocks.
  6.  *
  7.  * Copyright 1986 Regents of the University of California
  8.  * All rights reserved.
  9.  * Permission to use, copy, modify, and distribute this
  10.  * software and its documentation for any purpose and without
  11.  * fee is hereby granted, provided that the above copyright
  12.  * notice appear in all copies.  The University of California
  13.  * makes no representations about the suitability of this
  14.  * software for any purpose.  It is provided "as is" without
  15.  * express or implied warranty.
  16.  */
  17.  
  18. #ifndef lint
  19. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/dev/devSCSI.c,v 9.7 92/03/20 13:47:46 jhh Exp $ SPRITE (Berkeley)";
  20. #endif not lint
  21.  
  22.  
  23. #include <sprite.h>
  24. #include <mach.h>
  25. #include <dev.h>
  26. #include <devInt.h>
  27. #include <sys/scsi.h>
  28. #include <scsiDevice.h>
  29. #include <dbg.h>
  30. #include <vm.h>
  31. #include <sys.h>
  32. #include <sync.h>
  33. #include <fs.h>
  34. #include <sched.h>
  35. #include <stdio.h>
  36. #include <stdlib.h>
  37. #include <string.h>
  38. #include <bstring.h>
  39.  
  40. /*
  41.  * The error codes for class 0-6 sense data are class specific.
  42.  * The follow arrays of strings are used to print error messages.
  43.  */
  44. static char *Class0Errors[] = {
  45.     "No sense data",
  46.     "No index signal",
  47.     "No seek complete",
  48.     "Write fault",
  49.     "Drive notready",
  50.     "Drive not selected",
  51.     "No Track 00",
  52.     "Multiple drives selected",
  53.     "No address acknowledged",
  54.     "Media not loaded",
  55.     "Insufficient capacity",
  56. };
  57. static char *Class1Errors[] = {
  58.     "ID CRC error",
  59.     "Unrecoverable data error",
  60.     "ID address mark not found",
  61.     "Data address mark not found",
  62.     "Record not found",
  63.     "Seek error",
  64.     "DMA timeout error",
  65.     "Write protected",
  66.     "Correctable data check",
  67.     "Bad block found",
  68.     "Interleave error",
  69.     "Data transfer incomplete",
  70.     "Unformatted or bad format on drive",
  71.     "Self test failed",
  72.     "Defective track (media errors)",
  73. };
  74. static char *Class2Errors[] = {
  75.     "Invalid command",
  76.     "Illegal block address",
  77.     "Aborted",
  78.     "Volume overflow",
  79. };
  80. int devScsiNumErrors[] = {
  81.     sizeof(Class0Errors) / sizeof (char *),
  82.     sizeof(Class1Errors) / sizeof (char *),
  83.     sizeof(Class2Errors) / sizeof (char *),
  84.     0, 0, 0, 0, 0,
  85. };
  86. char **devScsiErrors[] = {
  87.     Class0Errors,
  88.     Class1Errors,
  89.     Class2Errors,
  90. };
  91.  
  92. int devSCSIDebug = FALSE;
  93.  
  94. /*
  95.  *----------------------------------------------------------------------
  96.  *
  97.  * DevScsiMapSense --
  98.  *
  99.  *    Map a SCSI Class7 Sense data structure into a Sprite ReturnStatus
  100.  *    and a printable error string.
  101.  *
  102.  * Results:
  103.  *    TRUE if the mapping succeeded. FALSE if the argument is not 
  104.  *    Class7 sense data.
  105.  *
  106.  * Side effects:
  107.  *    None.
  108.  *
  109.  *----------------------------------------------------------------------
  110.  */
  111. Boolean
  112. DevScsiMapClass7Sense(senseLength,senseDataPtr,statusPtr,errorString)
  113.     int        senseLength;    /* Length of the sense data at senseDataPtr. */
  114.     char    *senseDataPtr;    /* The sense data. */
  115.     ReturnStatus *statusPtr;    /* OUT - The Sprite ReturnStatus. */
  116.     char    *errorString;    /* OUT - A buffer to write a printable string
  117.                  * describing the data. Must be at least 
  118.                  * MAX_SCSI_ERROR_STRING in length. */
  119. {
  120.     register ScsiClass7Sense    *sensePtr = (ScsiClass7Sense *) senseDataPtr;
  121.     ReturnStatus    status;
  122.  
  123.     /*
  124.      * Default to no error string. 
  125.      */
  126.     *errorString = 0;
  127.  
  128.     if (senseLength < sizeof(ScsiClass7Sense)) {
  129.     return (FALSE);
  130.     }
  131.     if (sensePtr->error7 != 0x70) {
  132.     return (FALSE);
  133.     }
  134.  
  135.     switch (sensePtr->key) {
  136.     case SCSI_CLASS7_NO_SENSE:
  137.         status = SUCCESS;
  138.         break;
  139.     case SCSI_CLASS7_RECOVERABLE:
  140.         /*
  141.          * The drive recovered from an error.
  142.          */
  143.          (void) sprintf(errorString,
  144.             "recoverable error - info bytes 0x%x 0x%x 0x%x 0x%x",
  145.              sensePtr->info1, sensePtr->info2,
  146.              sensePtr->info3,sensePtr->info4);
  147.         status = SUCCESS;
  148.         break;
  149.     case SCSI_CLASS7_NOT_READY:
  150.         status = DEV_OFFLINE;
  151.         break;
  152.     case SCSI_CLASS7_MEDIA_ERROR:
  153.     case SCSI_CLASS7_HARDWARE_ERROR:
  154.          (void) sprintf(errorString,
  155.          "%s error - info bytes 0x%x 0x%x 0x%x 0x%x",
  156.         (sensePtr->key == SCSI_CLASS7_MEDIA_ERROR) ? "media" :
  157.                                  "hardware",
  158.         sensePtr->info1 & 0xff,
  159.         sensePtr->info2 & 0xff,
  160.         sensePtr->info3 & 0xff,
  161.         sensePtr->info4 & 0xff);
  162.         status = DEV_HARD_ERROR;
  163.         break;
  164.     case SCSI_CLASS7_ILLEGAL_REQUEST:
  165.         /*
  166.          * Probably a programming error.
  167.          */
  168.         (void) sprintf(errorString,"illegal request");
  169.         status = DEV_INVALID_ARG;
  170.         break;
  171.     case SCSI_CLASS7_UNIT_ATTN:
  172.         /*
  173.          * This is an error that occurs after the drive is reset.
  174.          */
  175.         (void) sprintf(errorString,"unit attention");
  176.         status = DEV_RESET;
  177.         break;
  178.     case SCSI_CLASS7_WRITE_PROTECT:
  179.         (void) sprintf(errorString,"write protected");
  180.         status = FS_NO_ACCESS;
  181.         break;
  182.     case SCSI_CLASS7_BLANK_CHECK:
  183.         (void) sprintf(errorString,
  184.         "blank check - info bytes  0x%x 0x%x 0x%x 0x%x",
  185.         sensePtr->info1,
  186.         sensePtr->info2,
  187.         sensePtr->info3,
  188.         sensePtr->info4);
  189.         status = DEV_HARD_ERROR;
  190.         break;
  191.     case SCSI_CLASS7_ABORT:
  192.         (void) sprintf(errorString,"command aborted");
  193.         status = DEV_RETRY_ERROR;
  194.         break;
  195.     case SCSI_CLASS7_VENDOR:
  196.     case SCSI_CLASS7_EQUAL:
  197.     case SCSI_CLASS7_OVERFLOW:
  198.         (void) sprintf(errorString,"unsupported class7 error 0x%x\n",
  199.             sensePtr->key);
  200.         status = DEV_HARD_ERROR;
  201.         break;
  202.     default: {
  203.         (void) sprintf(errorString,
  204.         "unknown class7 error 0x%x\n", sensePtr->key);
  205.         status = DEV_HARD_ERROR;
  206.         break;
  207.     }
  208.     }
  209.     *statusPtr = status;
  210.     return TRUE;
  211. }
  212.  
  213. /*
  214.  *----------------------------------------------------------------------
  215.  *
  216.  * DevScsiGroup0Cmd --
  217.  *
  218.  *      Setup a ScsiCmd block for a SCSI Group0 command.
  219.  *
  220.  * Results:
  221.  *    SUCCESS if the command block was filled in correctly, FAILURE
  222.  *    otherwise
  223.  *
  224.  * Side effects:
  225.  *    Set the various fields in the control block.
  226.  *
  227.  *----------------------------------------------------------------------
  228.  */
  229. ReturnStatus
  230. DevScsiGroup0Cmd(devPtr, cmd, blockNumber,countNumber,scsiCmdPtr)
  231.     ScsiDevice    *devPtr; /* SCSI device target for this command. */
  232.     int        cmd;     /* Group0 scsi command. */
  233.     unsigned int blockNumber;    /* The starting block number for the transfer */
  234.     unsigned int countNumber;    /* Number of sectors (or bytes!) to transfer */
  235.     register ScsiCmd    *scsiCmdPtr; /* Scsi command block to be filled in. */
  236. {
  237.     register  ScsiGroup0Cmd    *c;
  238.  
  239.     if ((cmd < 0) || (cmd > 0x1f)) {
  240.     panic("Bad SCSI command 0x%x giving to DevScsiGroup0Cmd.\n",cmd);
  241.     }
  242.     if (blockNumber > 0x1fffff) {
  243.     printf("DevScsiGroup0Cmd: block number too big (%d > %d)\n",
  244.         blockNumber, 0x1fffff);
  245.     return FAILURE;
  246.     }
  247.     if (countNumber > 0x100) {
  248.     printf("DevScsiGroup0Cmd: count too big (%d > %d)\n",
  249.         countNumber, 0x100);
  250.     return FAILURE;
  251.     }
  252.     bzero((char *)scsiCmdPtr, sizeof(ScsiCmd));
  253.     scsiCmdPtr->commandBlockLen = sizeof(ScsiGroup0Cmd);
  254.     c = (ScsiGroup0Cmd *) scsiCmdPtr->commandBlock;
  255.     c->command = cmd;
  256.     c->unitNumber = devPtr->LUN;
  257.     c->highAddr = (blockNumber & 0x1f0000) >> 16;
  258.     c->midAddr =  (blockNumber & 0x00ff00) >> 8;
  259.     c->lowAddr =  (blockNumber & 0x0000ff);
  260.     c->blockCount =  countNumber;
  261.     return SUCCESS;
  262. }
  263.  
  264. /*
  265.  *----------------------------------------------------------------------
  266.  *
  267.  * CopyAndTerminateString --
  268.  *
  269.  *    Copy a fixed length string into a null terminate string stripping
  270.  *    off the trailing blanks.
  271.  *
  272.  * Results:
  273.  *    None.
  274.  *
  275.  * Side effects:
  276.  *    None.
  277.  *
  278.  *----------------------------------------------------------------------
  279.  */
  280.  
  281. static void
  282. CopyAndTerminateString(length, string, outString)
  283.     int        length;    /* Length of the input string argument string. */
  284.     char    *string; /* Input string. */
  285.     char    *outString; /* Output string area. Must be at least (length+1) 
  286.                  * bytes. */
  287. {
  288.     /*
  289.      * Find last non blank charater in string. Update length of string.
  290.      */
  291.     while ( (length > 0) && (string[length] == ' ') ) {
  292.     length--;
  293.     }
  294.     /*
  295.      * Copy the string, terminate, and return.
  296.      */
  297.     bcopy(string, outString, length);
  298.     outString[length] = 0;
  299.     return;
  300. }
  301.  
  302.  
  303. /*
  304.  *----------------------------------------------------------------------
  305.  *
  306.  * DevScsiFormatInquiry --
  307.  *
  308.  *    Format SCSI inquiry data into a ascii string suitable for printing.
  309.  *
  310.  * Results:
  311.  *    The string length.
  312.  *
  313.  * Side effects:
  314.  *    None.
  315.  *
  316.  *----------------------------------------------------------------------
  317.  */
  318. int
  319. DevScsiFormatInquiry(dataPtr, outputString)
  320.     ScsiInquiryData *dataPtr;        /* Data structure returned by the 
  321.                      * SCSI inquiry command. 
  322.                      */
  323.     char    *outputString;        /* String to format into. */
  324. {
  325.     static char *deviceTypeNames[] = {
  326.     "Disk", "Tape", "Printer", "Processor", "WORM", "ROM",
  327.     };
  328.  
  329.     if (dataPtr->type > (sizeof(deviceTypeNames)/sizeof(char *))) {
  330.     /*
  331.      * If the device type is SCSI_NODEVICE_TYPE the rest of the
  332.      * data is not really meaningful so we return.
  333.      */
  334.     if (dataPtr->type == SCSI_NODEVICE_TYPE) {
  335.         (void) sprintf(outputString,"Logical unit not present");
  336.         return strlen(outputString);
  337.     } else {
  338.         (void) sprintf(outputString,"Unknown 0x%x",dataPtr->type);
  339.         return strlen(outputString);
  340.     }
  341.     } else {
  342.     (void) sprintf(outputString,"%s",deviceTypeNames[dataPtr->type]);
  343.     }
  344.     if (dataPtr->length < 0x1f) {
  345.     return strlen(outputString);
  346.     } else {
  347. #ifdef notdef
  348.     char    v[32], p[32], f[32];
  349.     CopyAndTerminateString(8,dataPtr->vendorInfo, v);
  350.     CopyAndTerminateString(8,dataPtr->productInfo, p);
  351.     CopyAndTerminateString(4,dataPtr->firmwareInfo, f);
  352.     (void) sprintf(outputString + strlen(outputString),"%s %s %s",v,p,f);
  353. #endif
  354.     char    v[32], p[32], rl[32], rd[32];
  355.     CopyAndTerminateString(8,(char *) (dataPtr->vendorID), v);
  356.     CopyAndTerminateString(16,(char *) (dataPtr->productID), p);
  357.     CopyAndTerminateString(4,(char *) (dataPtr->revLevel), rl);
  358.     CopyAndTerminateString(8,(char*) (dataPtr->revData), rd);
  359.     (void) sprintf(outputString + strlen(outputString),
  360.         "%s %s %s", v, p, rl, rd);
  361.     }
  362.     return strlen(outputString);
  363. }
  364.  
  365.